﻿//========================================================= 
/**@file ConsoleAppender.h
 * @brief 将日志输出到Console
 * 
 * @date 2018-06-18   11:36:17
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_CONSOLEAPPENDER_H_
#define _LIBZHOUYB_CONSOLEAPPENDER_H_
//--------------------------------------------------------- 
#include "../ILogCat.h"

#include <iostream>
//--------------------------------------------------------- 
namespace zhou_yb {
namespace extension {
namespace logcat {
//--------------------------------------------------------- 
#ifdef _WIN32
/// Windows下控制台日志颜色设置
class ConsoleColorSetter
{
protected:
    HANDLE _hConsole;
    WORD _oldAttribute;
public:
    ConsoleColorSetter()
    {
        _hConsole = GetStdHandle(STD_OUTPUT_HANDLE);

        CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
        GetConsoleScreenBufferInfo(_hConsole, &ConsoleScreenBufferInfo);
        _oldAttribute = ConsoleScreenBufferInfo.wAttributes;
    }
    void SetColor(LogLevel lv)
    {
        static const WORD WinColorFG[] =
        {
            // BLACK
            0,
            // RED
            FOREGROUND_RED,
            // GREEN
            FOREGROUND_GREEN,
            // BROWN
            FOREGROUND_RED | FOREGROUND_GREEN,
            // BLUE
            FOREGROUND_BLUE,
            // MAGENTA
            FOREGROUND_RED | FOREGROUND_BLUE,
            // CYAN
            FOREGROUND_GREEN | FOREGROUND_BLUE,
            // WHITE
            FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
            // YELLOW
            FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
            // RED_BOLD
            FOREGROUND_RED | FOREGROUND_INTENSITY,
            // GREEN_BOLD
            FOREGROUND_GREEN | FOREGROUND_INTENSITY,
            // BLUE_BOLD
            FOREGROUND_BLUE | FOREGROUND_INTENSITY,
            // MAGENTA_BOLD
            FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
            // CYAN_BOLD
            FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
            // WHITE_BOLD
            FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
        };

        int index = -1;
        switch(lv)
        {
        case LogAll:
        case LogTrace:
        case LogDebug:
            index = 2;
            break;
        case LogInfo:
            index = 6;
            break;
        case LogWarning:
            index = 7;
            break;
        case LogError:
            index = 5;
            break;
        case LogFatal:
            index = 1;
            break;
        case LogOff:
            break;
        }
        if(index != -1)
        {
            SetConsoleTextAttribute(_hConsole, WinColorFG[index]);
        }
    }
    void Reset()
    {
        SetConsoleTextAttribute(_hConsole, _oldAttribute);
    }
};
#else
class ConsoleColorSetter
{
public:
    void SetColor(LogLevel lv)
    {
        enum Color
        {
            BLACK,
            RED,
            GREEN,
            BROWN,
            BLUE,
            MAGENTA,
            CYAN,
            GREY,
            YELLOW,
            LRED,
            LGREEN,
            LBLUE,
            LMAGENTA,
            LCYAN,
            WHITE
        };

        enum ANSITextAttr
        {
            TA_NORMAL = 0,
            TA_BOLD = 1,
            TA_BLINK = 5,
            TA_REVERSE = 7
        };

        enum ANSIFgTextAttr
        {
            FG_BLACK = 30, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
            FG_MAGENTA, FG_CYAN, FG_WHITE, FG_YELLOW
        };

        enum ANSIBgTextAttr
        {
            BG_BLACK = 40, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
            BG_MAGENTA, BG_CYAN, BG_WHITE
        };

        static const byte UnixColorFG[] =
        {
            FG_BLACK,
            FG_RED,
            FG_GREEN,
            FG_BROWN,
            FG_BLUE,
            FG_MAGENTA,
            FG_CYAN,
            FG_WHITE,
            FG_YELLOW,
            FG_RED,
            FG_GREEN,
            FG_BLUE,
            FG_MAGENTA,
            FG_CYAN,
            FG_WHITE
        };
        int index = -1;
        switch(lv)
        {
        case LogAll:
        case LogTrace:
            index = GREY;
            break;
        case LogDebug:
            index = GREEN;
            break;
        case LogInfo:
            index = CYAN;
            break;
        case LogWarning:
            index = WHITE;
            break;
        case LogError:
            index = MAGENTA;
            break;
        case LogFatal:
            index = RED;
            break;
        case LogOff:
            break;
        }
        if(index != -1)
        {
            fprintf(stdout, "\x1b[%d%sm", UnixColorFG[index], index >= YELLOW ? ";1" : "");
        }
    }
    void Reset()
    {
        fprintf(stdout, "\x1b[0m");
    }
};
#endif
//--------------------------------------------------------- 
/// 控制台日志输出
class ConsoleAppender : public ILogAppender, public RefObject
{
public:
    ConsoleAppender() : IsEnableColor(true) {}

    bool IsEnableColor;
    virtual void append(LogLevel lv, const char* tag, const char* str)
    {
        if(!IsEnableColor)
        {
            std::cout << str << std::endl;
        }
        else
        {
            ConsoleColorSetter color;
            color.SetColor(lv);
            std::cout << str << std::endl;
            color.Reset();
        }
    }
};
//--------------------------------------------------------- 
} // namespace logcat
} // namespace extension
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_CONSOLEAPPENDER_H_
//========================================================= 